package org.inspursc.s0517.health.evaluation.service.impl;


import org.inspursc.s0517.health.common.dto.SysOrganizationDTO;
import org.inspursc.s0517.health.common.entity.SysUser;
import org.inspursc.s0517.health.common.service.SysOrganizationService;
import org.inspursc.s0517.health.common.util.SpringSecurityUtils;
import org.inspursc.s0517.health.evaluation.converter.SurveyConverter;
import org.inspursc.s0517.health.evaluation.dao.SurveyDao;
import org.inspursc.s0517.health.evaluation.dao.SurveyRelationDao;
import org.inspursc.s0517.health.evaluation.dto.QuestionCategoryDTO;
import org.inspursc.s0517.health.evaluation.dto.QuestionDTO;
import org.inspursc.s0517.health.evaluation.dto.SurveyDTO;

import org.inspursc.s0517.health.evaluation.dto.SurveyQuDetailDTO;
import org.inspursc.s0517.health.evaluation.entity.Survey;
import org.inspursc.s0517.health.evaluation.entity.SurveyRelation;
import org.inspursc.s0517.health.evaluation.service.QuestionCategoryService;
import org.inspursc.s0517.health.evaluation.service.QuestionService;
import org.inspursc.s0517.health.evaluation.service.SurveyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


@Service
public class SurveyServiceImpl implements SurveyService {

    @Autowired
    SysOrganizationService organizationService;

    @Autowired
    QuestionService questionService;

    @Autowired
    SurveyDao surveyDao;

    @Autowired
    QuestionCategoryService categoryService;

    @Autowired
    SurveyRelationDao relationDao;


    @Override
    @Transactional
    public SurveyDTO saveSurvey(SurveyDTO survey) {

        Survey t = SurveyConverter.converter(survey);
        Survey reSur = surveyDao.save(t);
        Integer surId = reSur.getId();
        List<Integer> questionIds = survey.getQuestionIds();
        List<SurveyRelation> relations = new ArrayList<>();
        for (Integer quStr : questionIds) {
            SurveyRelation relation = new SurveyRelation();
            relation.setQuestionId(quStr);
            relation.setSurveyId(surId);
            relations.add(relation);
        }
        relationDao.saveAll(relations);
        List<SurveyRelation> saveRela = relationDao.findAllBySurveyId(reSur.getId());
        List<Integer> quIds = new ArrayList<>();
        for (SurveyRelation re : saveRela) {
            quIds.add(re.getQuestionId());
        }
        SurveyDTO surDto = SurveyConverter.converter(reSur);
        surDto.setQuestionIds(quIds);
        return surDto;
    }


    @Override
    @Transactional
    public SurveyDTO updateSurvey(SurveyDTO surveyDTO) {
        Survey t = SurveyConverter.converter(surveyDTO);
            Survey newSur = surveyDao.save(t);
            List<Integer> questionIds = t.getQuestionIds();
            List<SurveyRelation> relations = new ArrayList<>();
            for (Integer quStr : questionIds) {
                SurveyRelation relation = new SurveyRelation();
                relation.setQuestionId(quStr);
                relation.setSurveyId(surveyDTO.getId());
                relations.add(relation);
            }
            relationDao.deleteAllBySurveyId(t.getId());
            List<SurveyRelation> surveyRelations = relationDao.saveAll(relations);
            List<Integer> quStrs = new ArrayList<>();
            surveyRelations.forEach(e -> quStrs.add(e.getQuestionId()));
            SurveyDTO newDTO = SurveyConverter.converter(newSur);
            newDTO.setQuestionIds(quStrs);
            return newDTO;
    }

    @Override
    public List<SurveyDTO> findSurvey() {
        List<Survey> surveys = surveyDao.findAll();
        surveys.forEach(survey -> survey.setQuestionIds(listQuIds(survey.getId())));
        List<SurveyDTO> suDtos = surveys.stream().map(SurveyConverter::converter).collect(Collectors.toList());
        return suDtos;
    }

    @Override
    public List<SurveyDTO> findSurveyByOrgIdAndUserId(HttpServletRequest request) throws Exception {

        if(request!=null) {
              SysUser sysUser = SpringSecurityUtils.getCurrentUser(request);
              if(sysUser!=null){
              Integer orgId= sysUser.getOrganizationId();
               SysOrganizationDTO organizationDTO= organizationService.findOneById(orgId);
               if(organizationDTO!=null) {
                  String ownSu= organizationDTO.getOwnSurvey();
                  if(!StringUtils.isEmpty(ownSu)) {
                      List<Integer> listIds = Arrays.asList(ownSu.split(",")).stream().map(s -> Integer.parseInt(s.trim())).collect(Collectors.toList());
                      List<Survey> surveys = findAllSurveyByOrgId(listIds);
                      if (surveys != null && surveys.size() != 0) {
                          List<SurveyDTO> surveyDTOS = surveys.stream().map(SurveyConverter::converter).collect(Collectors.toList());
                          return surveyDTOS;
                      }
                  }
               }
              }
        }
        return null;
    }

    @Override
    @Transactional
    public boolean deleteSurvey(Integer suId) {
        if (!StringUtils.isEmpty(suId)) {
            try {
                surveyDao.deleteById(suId);
                List<SurveyRelation> relations = relationDao.findAllBySurveyId(suId);
                relationDao.deleteInBatch(relations);
                return true;
            } catch (Exception e) {
                return false;
            }
        }
        return false;
    }

    private List<Integer> listQuIds(Integer suId) {

        List<SurveyRelation> relations = relationDao.findAllBySurveyId(suId);

        List<Integer> quIds = new ArrayList<>();
        relations.forEach(e -> {
            Integer quId = e.getQuestionId();
            quIds.add(quId);
        });
        return quIds;
    }

    @Override
    public SurveyDTO findOneSurvey(Integer surveyId) {
        Survey survey = surveyDao.getOne(surveyId);
        List<SurveyRelation> relations = relationDao.findAllBySurveyId(surveyId);
        SurveyDTO dto = SurveyConverter.converter(survey);
        dto.setQuestionIds(relations.stream().map(SurveyRelation::getQuestionId).collect(Collectors.toList()));
        return dto;
    }

    private List<Survey> findAllSurveyByOrgId(List<Integer> suIds){
        List<Survey> surveys=surveyDao.findAllById(suIds);
        surveys.forEach(e->{
            List<Integer> quIds=(relationDao.findAllBySurveyId(e.getId())).stream().map(SurveyRelation::getQuestionId).collect(Collectors.toList());
            e.setQuestionIds(quIds);
        });

        return surveys;

    }



    @Override
    public SurveyQuDetailDTO findOneSurveyDetail(Integer surveyId) throws Exception {


        //获取调查问卷信息
        Survey survey = surveyDao.getOne(surveyId);

        //根据问卷ID获取问卷题目ID及在问卷orderBy
        List<SurveyRelation> relations = relationDao.findAllBySurveyId(surveyId);

        SurveyQuDetailDTO dto = SurveyConverter.converterDetail(survey);

        List<Integer> quIds = relations.stream().map(SurveyRelation::getQuestionId).collect(Collectors.toList());

        List<QuestionDTO> questions = questionService.listQuestionsById(quIds);

        for (QuestionDTO qu : questions) {
            for (SurveyRelation sr : relations) {
                if (qu.getId().equals(sr.getQuestionId())) {
                    if(sr.getOrderBy()!=null){
                        qu.setOrderBy(sr.getOrderBy());
                    }else {
                        qu.setOrderBy(0);
                    }
                }
            }
        }
        //问题排序
        List<QuestionDTO> newQu = questions.stream().sorted(Comparator.comparing(QuestionDTO::getOrderBy)).collect(Collectors.toList());
        //按顺序组装到树
        List<QuestionCategoryDTO> categoryDTOS = categoryService.getCategoryOfSurvey(newQu);
        if (categoryDTOS.isEmpty()){
            throw new Exception("没有题库数据");
        }
        dto.setCategorys(categoryDTOS);

        return dto;

    }


}
